package com.ftwj.demo.base.common;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Component;

import com.ftwj.demo.base.cache.CustomCache;
import com.ftwj.demo.base.util.CacheUtil;

@Component
public class BaseNamedTemplate {
	
	@Autowired
	protected NamedParameterJdbcTemplate namedJtl;
	@Value("${spring.jdbctemplat.cache:false}")
	private boolean open;
	private String key;
	private CustomCache cache;

	@SuppressWarnings("unchecked")
	public <T> T query(String sql, SqlParameterSource paramSource, ResultSetExtractor<T> rse) throws DataAccessException {
		if(!open) return namedJtl.query(sql,paramSource,rse);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,rse,paramSource);
		T res = (T) cache.get(key);
		if(res!=null) return res;
		T data = namedJtl.query(sql,paramSource,rse);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T query(String sql, Map<String, ?> paramMap, ResultSetExtractor<T> rse) throws DataAccessException {
		if(!open) return namedJtl.query(sql,paramMap,rse);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,rse,paramMap);
		T res = (T) cache.get(key);
		if(res!=null) return res;
		T data = namedJtl.query(sql,paramMap,rse);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T query(String sql, ResultSetExtractor<T> rse) throws DataAccessException {
		if(!open) return namedJtl.query(sql,rse);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,rse);
		T res = (T) cache.get(key);
		if(res!=null) return res;
		T data = namedJtl.query(sql,rse);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public <T> List<T> query(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper) throws DataAccessException {
		if(!open) return namedJtl.query(sql,paramSource,rowMapper);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,rowMapper,paramSource);
		List<T> res =  (List<T>) cache.get(key);
		if(res!=null) return res;
		List<T> data = namedJtl.query(sql,paramSource,rowMapper);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public <T> List<T> query(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper) throws DataAccessException {
		if(!open) return namedJtl.query(sql,paramMap,rowMapper);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,rowMapper,paramMap);
		List<T> res =  (List<T>) cache.get(key);
		if(res!=null) return res;
		List<T> data = namedJtl.query(sql,paramMap,rowMapper);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException {
		if(!open) return namedJtl.query(sql,rowMapper);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,rowMapper);
		List<T> res =  (List<T>) cache.get(key);
		if(res!=null) return res;
		List<T> data = namedJtl.query(sql,rowMapper);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T queryForObject(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper) throws DataAccessException {
		if(!open) return namedJtl.queryForObject(sql,paramSource,rowMapper);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,rowMapper,paramSource);
		T res =  (T) cache.get(key);
		if(res!=null) return res;
		T data = namedJtl.queryForObject(sql,paramSource,rowMapper);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T queryForObject(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper) throws DataAccessException {
		if(!open) return namedJtl.queryForObject(sql,paramMap,rowMapper);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,rowMapper,paramMap);
		T res =  (T) cache.get(key);
		if(res!=null) return res;
		T data = namedJtl.queryForObject(sql,paramMap,rowMapper);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T queryForObject(String sql, SqlParameterSource paramSource, Class<T> requiredType) throws DataAccessException {
		if(!open) return namedJtl.queryForObject(sql,paramSource,requiredType);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,requiredType,paramSource);
		T res =  (T) cache.get(key);
		if(res!=null) return res;
		T data = namedJtl.queryForObject(sql,paramSource,requiredType);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T queryForObject(String sql, Map<String, ?> paramMap, Class<T> requiredType) throws DataAccessException {
		if(!open) return namedJtl.queryForObject(sql,paramMap,requiredType);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,requiredType,paramMap);
		T res =  (T) cache.get(key);
		if(res!=null) return res;
		T data = namedJtl.queryForObject(sql,paramMap,requiredType);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public Map<String, Object> queryForMap(String sql, SqlParameterSource paramSource) throws DataAccessException {
		if(!open) return namedJtl.queryForMap(sql,paramSource);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,paramSource);
		Map<String, Object> res =  (Map<String, Object>) cache.get(key);
		if(res!=null) return res;
		Map<String, Object> data = namedJtl.queryForMap(sql,paramSource);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public Map<String, Object> queryForMap(String sql, Map<String, ?> paramMap) throws DataAccessException {
		if(!open) return namedJtl.queryForMap(sql,paramMap);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,paramMap);
		Map<String, Object> res =  (Map<String, Object>) cache.get(key);
		if(res!=null) return res;
		Map<String, Object> data = namedJtl.queryForMap(sql,paramMap);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public <T> List<T> queryForList(String sql, SqlParameterSource paramSource, Class<T> elementType) throws DataAccessException {
		if(!open) return namedJtl.queryForList(sql,paramSource,elementType);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,elementType,paramSource);
		List<T> res = (List<T>) cache.get(key);
		if(res!=null) return res;
		List<T> data = namedJtl.queryForList(sql,paramSource,elementType);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public <T> List<T> queryForList(String sql, Map<String, ?> paramMap, Class<T> elementType) throws DataAccessException {
		if(!open) return namedJtl.queryForList(sql,paramMap,elementType);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,elementType,paramMap);
		List<T> res = (List<T>) cache.get(key);
		if(res!=null) return res;
		List<T> data = namedJtl.queryForList(sql,paramMap,elementType);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public List<Map<String, Object>> queryForList(String sql, SqlParameterSource paramSource) throws DataAccessException {
		if(!open) return namedJtl.queryForList(sql,paramSource);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,paramSource);
		List<Map<String, Object>> res = (List<Map<String, Object>>) cache.get(key);
		if(res!=null) return res;
		List<Map<String, Object>> data = namedJtl.queryForList(sql,paramSource);
		cache.put(key, data);
		return data;
	}
	
	@SuppressWarnings("unchecked")
	public List<Map<String, Object>> queryForList(String sql, Map<String, ?> paramMap) throws DataAccessException {
		if(!open) return namedJtl.queryForList(sql,paramMap);
		cache=CacheUtil.getCache();
		key=CacheUtil.getKey(sql,paramMap);
		List<Map<String, Object>> res = (List<Map<String, Object>>) cache.get(key);
		if(res!=null) return res;
		List<Map<String, Object>> data = namedJtl.queryForList(sql,paramMap);
		cache.put(key, data);
		return data;
	}
	
	public int update(String sql, SqlParameterSource paramSource) throws DataAccessException {
		if(!open) return namedJtl.update(sql,paramSource);
		cache=CacheUtil.getCache();
		cache.clear();
		return namedJtl.update(sql,paramSource);
	}
	
	public int update(String sql, Map<String, ?> paramMap) throws DataAccessException {
		if(!open) return namedJtl.update(sql,paramMap);
		cache=CacheUtil.getCache();
		cache.clear();
		return namedJtl.update(sql,paramMap);
	}
	
	public int update(String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder) throws DataAccessException {
		if(!open) return namedJtl.update(sql,paramSource,generatedKeyHolder);
		cache=CacheUtil.getCache();
		cache.clear();
		return namedJtl.update(sql,paramSource,generatedKeyHolder);
	}
	
	public int update(String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder, String[] keyColumnNames) throws DataAccessException {
		if(!open) return namedJtl.update(sql,paramSource,generatedKeyHolder,keyColumnNames);
		cache=CacheUtil.getCache();
		cache.clear();
		return namedJtl.update(sql,paramSource,generatedKeyHolder,keyColumnNames);
	}

	public int[] batchUpdate(String sql, Map<String, ?>[] batchValues) {
		if(!open) return namedJtl.batchUpdate(sql, batchValues);
		cache=CacheUtil.getCache();
		cache.clear();
		return namedJtl.batchUpdate(sql, batchValues);
	}

}
